package com.yc.damai.web;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yc.damai.bean.SecondKill;
import com.yc.damai.bean.SecondKillItem;
import com.yc.damai.entity.DmOrderitem;
import com.yc.damai.entity.DmOrders;
import com.yc.damai.entity.DmProduct;
import com.yc.damai.entity.DmUser;
import com.yc.damai.mapper.DmOrderitemMapper;
import com.yc.damai.mapper.DmOrdersMapper;
import com.yc.damai.mapper.DmProductMapper;
import com.yc.login.vo.Result;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/*
* 秒杀:在某个时间点开始对某类商品进行促销的活动,秒杀有时间限制.

1. 商户设置秒杀(大促)活动
	1) 开始时间,结束时间,价格策略...
	2) 参与商品的集合
	1对多关系

2. 一旦生成秒杀的数据, 那么产生定时任务
3. 到达活动开始的时间, 自动启动任务
4. 查询出参与活动的商品, 保存到redis中
5. 数据库中减去参与秒杀的商品的数量
6. 响应用户请求, 生成秒杀订单(单独的订单方法)
     redis + rabbitMQ
7. 秒杀结束, 将秒杀剩余的商品数量加入数据库
*
* */
@RestController
public class SecondKillDo {

    //当前秒杀活动的对象 TODO： 扩展： 保存在Redis中
    private SecondKill currentSecondKill;

    //查询商品  TODO  远程调用other 查询
    @Resource
    private DmProductMapper productMapper;


    @Resource
    private TaskScheduler taskScheduler;


    //使用定时任务  启动秒杀 TODO 参考springboot定时任务
    @RequestMapping("nextSecondKill")
    public  SecondKill nextSecondKill(){

        if(currentSecondKill!=null){
            //秒杀已经开始
            return currentSecondKill;
        }

        //直接构建 TODO  查询数据库的记录
        SecondKill sk = new SecondKill();
       // LocalDateTime startTime=LocalDateTime.of(2024,5,19,16,0,0);
        LocalDateTime startTime=LocalDateTime.now().plusSeconds(10);
        sk.setStartTime(startTime);
        //LocalDateTime endTime=LocalDateTime.of(2024,5,19,17,0,0);
        LocalDateTime endTime= startTime.plusSeconds(600);
        sk.setEndTime(endTime);
        sk.setRate(0.8);
        //查询商品: 查询库存最多的10个商品
        IPage<DmProduct> page = new Page<>(1, 10);
        page.orders().add(OrderItem.desc("store"));
        IPage<DmProduct> iPage = productMapper.selectPage(page, null);
        //将List<Product> 转为 List<SecondKillItem>
        sk.setProducts(iPage.getRecords().stream().map(product->{
            SecondKillItem secondKillItem = new SecondKillItem();
            secondKillItem.setProduct(product);
            //计算折扣价
            secondKillItem.setPrice(product.getShopPrice()*sk.getRate());
            return secondKillItem;
        }).collect(Collectors.toList()));
        currentSecondKill = sk;

        //扣减库存
        for(SecondKillItem secondKillItem:sk.getProducts()){
            //扣减库存 100
            secondKillItem.getProduct().setStore(
                    secondKillItem.getProduct().getStore()-100);
            productMapper.updateById(secondKillItem.getProduct());

            //设置秒杀数量 100
            secondKillItem.getProduct().setStore(100);

        }

        //根据时区获取 秒值
        long time = currentSecondKill.getEndTime().toEpochSecond(ZoneOffset.ofHours(8));
        System.out.println(time);

        //将秒值转为毫秒值
        Date finishDate = new Date(time * 1000);
        //开启延时任务    秒杀活动终止
        taskScheduler.schedule(()->{
           finish();
        },finishDate );



        return currentSecondKill;


    }


    public static void main(String[] args) {
        System.out.println("LocalDateTime.now() = " + LocalDateTime.now());
        long time = LocalDateTime.now()
                .toEpochSecond(ZoneOffset.ofHours(8));
        System.out.println("time = " + time);
        Date finishDate = new Date(time*1000);
        System.out.println("finishDate = " + finishDate);
    }


    private void finish(){
        //将秒杀剩余的商品数量加入数据库
        for(SecondKillItem secondKillItem:currentSecondKill.getProducts()){
            DmProduct dbProduct = productMapper.selectById(secondKillItem.getProduct().getId());
            dbProduct.setStore(dbProduct.getStore()+secondKillItem.getProduct().getStore());
            productMapper.updateById(dbProduct);
        }

        //currentSecondKill  置空
        currentSecondKill = null;

    }

    //假定每次秒杀只能 秒杀一个商品 TODO 秒杀购物车
    @RequestMapping("secondKill")
    public synchronized Result secondKill(@SessionAttribute(required = false) DmUser loginedUser,
                             int pid){

        if(currentSecondKill == null ||
            currentSecondKill.getStartTime().isBefore(LocalDateTime.now()) == false){
            System.out.println(currentSecondKill );
            return new Result(-1,"秒杀活动尚未开始",null);

        }

        if(loginedUser == null){
            return new Result(0,"请先登录系统",null);
        }

        //TODO Redis 中完成下列操作
        List<SecondKillItem> list = currentSecondKill.getProducts()
                .stream()
                .filter(ski -> ski.getProduct().getId() == pid)
                .collect(Collectors.toList());
        if(list.isEmpty()){
            return new Result(-2,"该商品未参与秒杀",null);
        }
        DmProduct product = list.get(0).getProduct();
        if(product.getStore() == 0){
            return new Result(-3,"该商品已售完",null);
        }
        product.setStore(product.getStore()-1);

        // TODO 未完待续...
        DmOrders order = new DmOrders();
        order.setUid(loginedUser.getId());
        DmOrderitem item = new DmOrderitem();
        item.setPid(pid);
        order.setItems(new ArrayList<>());
        order.getItems().add(item);
        //发送消息到名为 "skQueue" 的队列，并且发送的消息内容是 order 对象
        rabbitTemplate.convertAndSend("skQueue", order);

        //向消息队列发送订单消息 通过消息队列 将uid 和pid 发送给秒杀订单方法
        System.out.println("向消息队列发送订单消息 通过消息队列 将uid 和pid 发送给秒杀订单方法");

        return new Result(1,"秒杀成功",null);


    }


    @Resource
    RabbitTemplate rabbitTemplate;
//    @Resource
//    DmOrdersMapper ordersMapper;
//    @Resource
//    DmOrderitemMapper orderitemMapper;
//
//    // TODO 秒杀订单的方法 , 定义在 other 中, 通过 消息队列 + 调用other方法方式执行
//    @Transactional
//    @RabbitListener(queuesToDeclare = @Queue("skQueue"))
//    public void secondKillOrder(DmOrders order){
//        // aid 收货地址
//        // 与普通的区别, 少了扣减库存的操作
//
//        Integer pid = order.getItems().get(0).getPid();
//        DmProduct dmProduct = productMapper.selectById(pid);
//
//        order.setTotal(dmProduct.getShopPrice());
//        order.setAid(order.getAid());
//        order.setState(1);
//        order.setCreatetime(LocalDateTime.now());
//        ordersMapper.insert(order);
//        for (DmOrderitem item : order.getItems()) {
//            item.setOid(order.getId());
//            item.setCount(1);
//            item.setTotal(dmProduct.getShopPrice());
//            orderitemMapper.insert(item);
//        }
//        System.out.println("秒杀订单完成");
//
//    }

    @RequestMapping("querySKProduct")
    public SecondKill querySKProduct(){
        if(currentSecondKill.getStartTime().isBefore(LocalDateTime.now()) == false){
            return null;
        }

        return currentSecondKill;
    }



}
